﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Niagara.Core;
using System.Xml.Linq;
using System.IO;
using System.Data.Services.Design;
using System.Text.RegularExpressions;
using System.Reflection;

namespace Niagara.UnitTests
{
  /// <summary>
  /// Summary description for ServiceProxyGeneratorTests
  /// </summary>
  [TestClass]
  public class ServiceProxyGeneratorTests
  {

    TestContext testContextInstance;
    XDocument edmDoc = null;
    MemoryStream strm = null;
    StreamWriter writer = null;
    ValidationDataServiceProxyGenerator gen = null;

    /// <summary>
    ///Gets or sets the test context which provides
    ///information about and functionality for the current test run.
    ///</summary>
    public TestContext TestContext
    {
      get
      {
        return testContextInstance;
      }
      set
      {
        testContextInstance = value;
      }
    }

    [TestInitialize]
    public void SetupTest()
    {
      edmDoc = XDocument.Load(string.Concat(Directory.GetCurrentDirectory(), "\\service.edmx"));
      strm = new MemoryStream();
      writer = new StreamWriter(strm);
      gen = new ValidationDataServiceProxyGenerator(edmDoc.CreateReader(), 
        writer, 
        "AgiliTrain.Data",
        new ReflectionAttributeMetadataProvider(Assembly.LoadFile(string.Concat(Directory.GetCurrentDirectory(), "\\XBoxGames.Data.dll"))));
    }

    [TestCleanup]
    public void TeardownTest()
    {
      edmDoc = null;
      writer.Dispose();
      writer = null;
      strm = null;
      gen = null;
    }


    [TestMethod]
    public void TestGeneratorDefaults()
    {
      Assert.IsTrue(gen.DataServiceVersion == DataServiceCodeVersion.V1, "Default DataServiceVersion should be Version 1");
      Assert.IsTrue(gen.Language == LanguageOption.GenerateCSharpCode, "Default Language should be C#");
      Assert.IsFalse(gen.UseDataServiceCollection, "UseDataServiceCollection should be false by default");
      Assert.IsFalse(gen.GenerateValidation, "GenerateValidation should be false by default");
    }

    [TestMethod]
    public void TestGeneratorSettings()
    {
      gen.DataServiceVersion = DataServiceCodeVersion.V2;
      gen.GenerateValidation = true;
      gen.Language = LanguageOption.GenerateVBCode;
      gen.UseDataServiceCollection = true;

      Assert.IsTrue(gen.DataServiceVersion == DataServiceCodeVersion.V2, "Setting DataServiceCodeVersion should hold the value.");
      Assert.IsTrue(gen.Language == LanguageOption.GenerateVBCode, "Setting Language should hold the value.");
      Assert.IsTrue(gen.UseDataServiceCollection, "Setting UseDataServiceCollection should hold the value.");
      Assert.IsTrue(gen.GenerateValidation, "Setting GenerateValidation should hold the value.");
    }

    [TestMethod]
    public void TestGeneratorCSharpOutput()
    {
      gen.DataServiceVersion = DataServiceCodeVersion.V2;
      gen.GenerateValidation = true;
      gen.UseDataServiceCollection = true;

      var errors = gen.GenerateCode();
      Assert.IsTrue(errors.Count == 0, "Code Generation Should happen without any errors.");
      strm.Position = 0;
      var code = new StreamReader(strm).ReadToEnd();
      File.CreateText("test.cs").Write(code);
      Assert.IsTrue(Regex.IsMatch(code, "System.ComponentModel.DataAnnotations.Required"), "Code Generation should create Required Attribute.");
      Assert.IsTrue(Regex.IsMatch(code, "System.ComponentModel.DataAnnotations.StringLength"), "Code Generation should create StringLength Attribute.");
      Assert.IsTrue(Regex.IsMatch(code, @"this.ValidateProperty\(""Name"", value\);"), "Code Generation should create calls to ValidateProperty.");
      Assert.IsTrue(Regex.IsMatch(code, @"protected virtual void ValidateProperty\(string propertyName, object value\)"), "Code Generation should create ValidateProperty method.");
    }

    [TestMethod]
    public void TestGeneratorVBOutput()
    {
      gen.Language = LanguageOption.GenerateVBCode;
      gen.DataServiceVersion = DataServiceCodeVersion.V2;
      gen.GenerateValidation = true;
      gen.UseDataServiceCollection = true;

      var errors = gen.GenerateCode();
      Assert.IsTrue(errors.Count == 0, "Code Generation Should happen without any errors.");
      strm.Position = 0;
      var code = new StreamReader(strm).ReadToEnd();
      File.CreateText("test.vb").Write(code);
      Assert.IsTrue(Regex.IsMatch(code, "System.ComponentModel.DataAnnotations.Required"), "Code Generation should create Required Attribute.");
      Assert.IsTrue(Regex.IsMatch(code, "System.ComponentModel.DataAnnotations.StringLength"), "Code Generation should create StringLength Attribute.");
      Assert.IsTrue(Regex.IsMatch(code, @"Me.ValidateProperty\(""Name"", value\)"), "Code Generation should create calls to ValidateProperty.");
      Assert.IsTrue(Regex.IsMatch(code, @"Protected Overridable Sub ValidateProperty\(ByVal propertyName As String, ByVal value As Object\)"), "Code Generation should create ValidateProperty method.");
    }

  }
}
